// ----------------------------------------------------------------------------
// registration_object.cpp
// ----------------------------------------------------------------------------
#include <fw/base/runtime/registration_object.h>
#include <fw/base/core/assertion.h>
#include <stdlib.h>

namespace fw
{
	RegisteredObjectInterface::RegisteredObjectInterface( const char* 	pName, 
														 int			priority )
	: m_pName	( pName )
	, m_priority( priority )
	{
		Register::RegisterObject( (*this) );
	}
	
	RegisteredObjectInterface::~RegisteredObjectInterface()
	{
		Register::UnregisterObject( (*this ) );
	}
	
	const char* RegisteredObjectInterface::GetName() const
	{
		return m_pName;
	}
	
	int RegisteredObjectInterface::GetPriority() const
	{
		return m_priority;
	}
	
	int RegisteredObjectInterface::IsLessPriority( const void* pL, const void* pR )
	{
		const RegisteredObjectInterface* pLeft  = *(const RegisteredObjectInterface**)pL;
		const RegisteredObjectInterface* pRight = *(const RegisteredObjectInterface**)pR;
		return ( pLeft->m_priority >  pRight->m_priority ) ? -1 : 1;
	}
	
	RegisteredFunction::RegisteredFunction( const char*				pName, 
										   PFnRegisteredFunction	pFunction,
										   int						priority )
	: RegisteredObjectInterface( pName, priority )
	, m_pFunction( pFunction )
	{
		FW_ASSERT( m_pFunction != 0, L"登録すべき関数が見つかりませんでした.\n" );
	}
	
	void RegisteredFunction::operator()( const ObjectOperation operation )
	{
		(*m_pFunction)( operation );
	}
	
	Register::RegisteredList* Register::s_pRegisteredObjects = 0;
	
	int Register::s_registeredObjectsCount = 0;
	
	void Register::CallInitialize()
	{
		if( !s_pRegisteredObjects )
		{
			return;
		}
		qsort( s_pRegisteredObjects, s_registeredObjectsCount, sizeof(RegisteredList), RegisteredObjectInterface::IsLessPriority );
		
		for(int i=0; i<s_registeredObjectsCount; ++i)
		{
			(*s_pRegisteredObjects[i])( FW_REGISTER_ON_INITIALIZE );
		}
	}
	
	void Register::CallDestroy()
	{
		if( !s_pRegisteredObjects )
		{
			return;
		}
		for(int i=s_registeredObjectsCount-1; i>=0 ;--i)
		{
			(*s_pRegisteredObjects[i])( FW_REGISTER_ON_DESTROY );
		}
	}
	
	void Register::DumpRegisteredObject()
	{
		if( !s_pRegisteredObjects )
		{
			FW_WPRINTF(L"登録オブジェクトはありません.\n");
			return;
		}
		qsort( s_pRegisteredObjects, s_registeredObjectsCount, sizeof(RegisteredList), RegisteredObjectInterface::IsLessPriority );
		
		FW_PRINTF("-----------------------------------------------------------------------\n");
		FW_WPRINTF(L"登録オブジェクト / プライオリティ.\n");
		//		FW_FOREACH( it, (*s_pRegisteredObjects), RegisteredList )
		for(int i=0; i<s_registeredObjectsCount; ++i)
		{
			FW_PRINTF( "%s (%d)\n", s_pRegisteredObjects[i]->GetName(), s_pRegisteredObjects[i]->GetPriority() );
			//			FW_PRINTF( "%s (%d)\n", (*it)->GetName(), (*it)->GetPriority() );
		}
		FW_PRINTF("-----------------------------------------------------------------------\n\n");
	}
	
	void Register::RegisterObject( RegisteredObjectInterface& rObject )
	{
		static const int kMaxRegisteredObject = 64;
		
		if( !s_pRegisteredObjects )
		{
			//static Register::RegisteredList ls_registeredList;
			//s_pRegisteredObjects = &ls_registeredList;
			static RegisteredList ls_registeredList[kMaxRegisteredObject];
			s_pRegisteredObjects = ls_registeredList;
			s_registeredObjectsCount = 0;
		}
		if(s_registeredObjectsCount<kMaxRegisteredObject)
		{
			s_pRegisteredObjects[s_registeredObjectsCount] = &rObject;
			s_registeredObjectsCount++;
		}
		else
		{
			FW_WPRINTF(L"登録オブジェクトの上限数%dを超えました.\n", kMaxRegisteredObject);
		}
		FW_ASSERT(s_registeredObjectsCount<kMaxRegisteredObject, L"登録オブジェクトの上限を超えました.\n");
	}
	
	void Register::UnregisterObject( RegisteredObjectInterface& rObject )
	{
		//ここに来ているということは最低限一回はRegisterObjectが呼ばれているはず. 
		FW_ASSERT( s_pRegisteredObjects != 0, L"Register::RegisterObjectを呼び出す前にRegister::UnregisterObjectを呼び出しました.\n" );
	}
		
} /* namespace fw */


